
package com.sensor;

import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;


/**
 * @author Mac
 *
 */
/**
 * @author Mac
 *
 */
/**
 * @author Mac
 *
 */
public class RSFFrame {
	public enum OpType{
		QUERY(1),
		SETIP(2),
		REPLY(3);
		
		private int value = 0;
	    private OpType(int value) {    //    ������private�ģ�����������
	        this.value = value;
	    }
	    public static OpType valueOf(int value) {    //    ��д�Ĵ�int��enum��ת������
	        switch (value) {
	        case 1:
	            return QUERY;
	        case 2:
	            return SETIP;
	        case 3:
	        	return REPLY;
	        default:
	            return null;
	        }
	    }

	    public int value() {
	        return this.value;
	    }
	}
	/*
	 * �㲥��:
	 * byte opcode ������. RSF_QUERY=01, RSF_SETIP=02, RSF_RELAY=03
	 * unsigned long flag	Ӳ����ʾ0x58292020 MQӲ����ʾ
	 * byte[6] source_hwaddr	���Ͷ���̫���ַ
	 * unsigned long source_ipaddr ���Ͷ�IP��ַ
	 * byte[6] dest_hwaddr	Ŀ����̫���ַ
	 * unsigned long dest_inaddr Ŀ��IP��ַ*/
	public byte opcode;
	public int mFlag = 0x20202958; //0x58292020;0x20202958
	public byte[] src_hw_addr = new byte[6];
	public int src_ip_addr;
	public byte[] dst_hw_addr = new byte[6];
	public int dst_ip_addr;
	public final int space = 0;
	
	public RSFFrame(){
		super();
	}
	/**
	 * 
	 * @param opcode
	 * @param flag
	 * @param src_hw_addr
	 * @param src_ip_addr
	 * @param dst_hw_addr
	 * @param dst_ip_addr
	 */
	public RSFFrame(byte opcode, int flag, byte[]src_hw_addr, int src_ip_addr, byte[] dst_hw_addr, int dst_ip_addr) {
		super();
		this.opcode = opcode;
		this.mFlag = flag;
		this.src_hw_addr = src_hw_addr;
		this.src_ip_addr = src_ip_addr;
		this.dst_hw_addr = dst_hw_addr;
		this.dst_ip_addr = dst_ip_addr;
	}
	/**
	 * 
	 * @return
	 */
	byte[] GetByteStream(){
		ByteBuffer buf = ByteBuffer.allocate(30);
		buf.put(opcode);
		buf.putInt(mFlag);
		buf.put(src_hw_addr);
		buf.putInt(src_ip_addr);
		buf.put(dst_hw_addr);
		buf.putInt(dst_ip_addr);
		buf.putInt(space);
		buf.flip();
		return buf.array();
	}
	/**
	 * 
	 * @param buf
	 * @return
	 */
	boolean FromByteStream(byte[] buf){
		if (buf.length < 25){
			System.out.print("len not enough: " + buf.length + "!\n");
			return false;
		}
		ByteBuffer buf_recv = ByteBuffer.wrap(buf);
		//buf_recv.flip();
		opcode = buf_recv.get();
		mFlag = buf_recv.getInt();
		buf_recv.get(src_hw_addr, 0, 6);
		src_ip_addr = buf_recv.getInt();
		buf_recv.get(dst_hw_addr, 0, 6);
		dst_ip_addr = buf_recv.getInt();
		return true;
	}
	
	@Override
	public String toString(){
		String retval;
		retval = "(opcode: " + GetOpString(OpType.valueOf(opcode))
				+ ", hw_flag: 0x" + Integer.toHexString(mFlag)
				+ ", src_hw:" + ByteArrayToMac(src_hw_addr)
				+ ", src_ip:" + IntegerToIp(src_ip_addr)
				+ ", dst_hw:" + ByteArrayToMac(dst_hw_addr)
				+ ", dst_ip:" + IntegerToIp(dst_ip_addr)
				+ ")";
		return retval;
	}
	
	void SetOpCode(OpType op){
		switch(op){
		case QUERY:
			opcode = 0x01;
			break;
		case SETIP:
			opcode = 0x02;
			break;
		case REPLY:
			opcode = 0x03;
			break;
		default:
			opcode = 0x00;
			break;
		}
	}
	/**
	 * 
	 * @param op
	 * @return
	 */
	String GetOpString(OpType op){
		switch (op){
		case QUERY:
			return "query";
		case SETIP:
			return "setip";
		case REPLY:
			return "reply";
		default:
			return "unknown";
		}
	}
	/**
	 * 
	 * @param flag
	 */
	void SetHardwareFlag(int flag){
		mFlag = flag;
	}
	
	private String IntegerToIp(int ip_addr){
	    byte[] bytes = BigInteger.valueOf(ip_addr).toByteArray();
	    try {
			InetAddress address = InetAddress.getByAddress(bytes);
			return address.toString();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 
	 * @param hw_mac_addr
	 * @return
	 */
	private String ByteArrayToMac(byte[] hw_mac_addr){
		StringBuilder mac_sb = new StringBuilder();
	    for (int i = 0; i < dst_hw_addr.length; i++) {
	    	mac_sb.append(String.format("%02X%s", hw_mac_addr[i], (i < hw_mac_addr.length - 1) ? "-" : ""));         
	    }
		return mac_sb.toString();
	}
	
}
